package jbox2dprocessing.compontent;

import org.jbox2d.collision.AABB;
import org.jbox2d.collision.Shape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.joints.MouseJoint;
import org.jbox2d.dynamics.joints.MouseJointDef;

import pbox2d.PBox2D;
import processing.core.PApplet;
import shared.BVZClientToServerMessages;

public class MouseInteraction {
	public static PApplet parent;
	public MouseJoint mouseJoint;
	
	PBox2D box2d;
		
	public MouseInteraction(PBox2D _box2d) {
		mouseJoint = null;
		this.box2d = _box2d;
	}
	
	public void update(float x, float y){
		if(mouseJoint != null){
			Vec2 mouseWorld = box2d.screenToWorld(x, y);
			mouseJoint.setTarget(mouseWorld);
		}
	}
	
	public void display(){
		if(mouseJoint != null){
			Vec2 v1 = mouseJoint.getAnchor1();
			Vec2 v2 = mouseJoint.getAnchor2();
			
			v1 = box2d.worldToScreen(v1);
			v2 = box2d.worldToScreen(v2);
			
			parent.stroke(0);
			parent.strokeWeight(1);
			parent.line(v1.x, v1.y, v2.x, v2.y);
		}
	}
	
	public void bind(float x, float y, Body body){
		MouseJointDef md = new MouseJointDef();
		md.body1 = box2d.world.getGroundBody();
		md.body2 = body;
		
		Vec2 mp = box2d.screenToWorld(x, y);
		md.target.set(mp);
		
		md.maxForce = 1000.0f * body.m_mass;
		md.frequencyHz = 50.0f;
		md.dampingRatio = 1.0f;
		
		body.wakeUp();
		
		mouseJoint = (MouseJoint) box2d.world.createJoint(md);
	}
	
	public void changeBind(PhysBox box){
		mouseJoint.m_body2 = box.baseBody;
	}
	
	public void destory(){
		if(mouseJoint != null){
			box2d.world.destroyJoint(mouseJoint);
			mouseJoint = null;
		}
	}
	
	public Body getBodyAtMouse(){
		Vec2 mouseWorld = box2d.screenToWorld(parent.mouseX, parent.mouseY);
		AABB aabb = new AABB();
		aabb.lowerBound.set((float)(mouseWorld.x - 0.001), (float)(mouseWorld.y - 0.001));
		aabb.upperBound.set((float)(mouseWorld.x + 0.001), (float)(mouseWorld.y + 0.001));
		
		int k_maxCount = 10;
		Shape[] count = box2d.world.query(aabb, k_maxCount);
		Body body = null;
		for (int i = 0; i < count.length; i++) {
			if(count[i].getBody().isStatic() == false){
				boolean isInside = count[i].testPoint(count[i].getBody().getXForm(), mouseWorld);
				if(isInside){
					body = count[i].getBody();
					break;
				}
			}
		}
		return body;
	}
	
	public Body getBodyAtClientMouse(BVZClientToServerMessages msg){
		Vec2 mouseWorld = box2d.screenToWorld(msg.mousePosX, msg.mousePosY);
		AABB aabb = new AABB();
		aabb.lowerBound.set((float)(mouseWorld.x - 0.001), (float)(mouseWorld.y - 0.001));
		aabb.upperBound.set((float)(mouseWorld.x + 0.001), (float)(mouseWorld.y + 0.001));
		
		int k_maxCount = 10;
		Shape[] count = box2d.world.query(aabb, k_maxCount);
		Body body = null;
		for (int i = 0; i < count.length; i++) {
			if(count[i].getBody().isStatic() == false){
				boolean isInside = count[i].testPoint(count[i].getBody().getXForm(), mouseWorld);
				if(isInside){
					body = count[i].getBody();
					break;
				}
			}
		}
		return body;
	}

}















